#include "findNeuronMaxError.h"
#include <math.h>
#include <float.h>
#include "../calcError.h"

FindNeuronMaxError::FindNeuronMaxError() : m_error_value(ZERO_ERROR_VALUE),
                                           m_neuron_id(NONE_NEURON_ID)
{
}

FindNeuronMaxError::~FindNeuronMaxError()
{
}

ntype::neuronid_t FindNeuronMaxError::getNeuronID() const
{
 return m_neuron_id;
}


ntype::error_t FindNeuronMaxError::getError() const
{
    return m_error_value;
}

void FindNeuronMaxError::clearError()
{
    m_error_value = ZERO_ERROR_VALUE;
    m_neuron_id   = NONE_NEURON_ID;
}

bool FindNeuronMaxError::start()
{
  ntype::error_t  error = 0.0;
  if(neuron_count_max == 0 || pneuron == NULL) return false;

  clearError();
  for(ntype::neuroncount_t neuron_count = 0; neuron_count < neuron_count_max; neuron_count ++)
  {
//    error = getNeuronSynapseError(pneuron[neuron_count]);
      error = getNeuronAxonError(pneuron[neuron_count]);
    if(error > m_error_value)
    {
      m_error_value = error;
      m_neuron_id   = neuron_count;
    }
  }
  return true;
}

ntype::error_t FindNeuronMaxError::getNeuronSynapseError(const neuron& n)
{
    const ntype::synapsecount_t max_synapse_id_count = n.getSynapseCount();
    ntype::error_t              result = 0.0;
    for(ntype::synapsecount_t synapse_id = 0; synapse_id < max_synapse_id_count; synapse_id++)
    {
      result += getSynapseError(n, synapse_id);
    }
    result = result / (double)max_synapse_id_count;
    return result;
}


ntype::error_t FindNeuronMaxError::getNeuronAxonError(const neuron& n)
{
    const ntype::signalid_t max_sig_id = n.getMaxSignalStudyBufferIndex();
    ntype::signal_t         fsignal;
    ntype::signal_t         bsignal;
    ntype::error_t          result = 0.0;
    for(ntype::signalid_t sig_id_count = 0; sig_id_count < max_sig_id; sig_id_count ++)
    {
       fsignal = n.getAxon().getFStudySignal(sig_id_count);
       bsignal = n.getAxon().getBStudySignal(sig_id_count);
       result += getSignalErrorValueAbs(fsignal, bsignal, ALLOWED_ERROR_RANGE);
    }
    result = result / (ntype::error_t)max_sig_id;
    return result;
}



ntype::error_t FindNeuronMaxError::getSynapseError(const neuron& n, ntype::synapseid_t synID)
{
    const ntype::signalid_t max_sig_id = n.getMaxSignalStudyBufferIndex();
    ntype::signal_t         fsignal;
    ntype::signal_t         bsignal;
    ntype::error_t          local_result = 0.0;
    ntype::error_t          result = 0.0;
    for(ntype::signalid_t sig_id_count = 0; sig_id_count < max_sig_id; sig_id_count ++)
    {
       fsignal = n.getSynapse(synID).getFSignalStudy(sig_id_count);
       bsignal = n.getSynapse(synID).getBSignalStudy(sig_id_count);

       local_result = ((fsignal - bsignal) / bsignal);
       result += fabs(local_result);
    }
    result = result / (ntype::error_t)max_sig_id;
    return result;
}

